﻿/*
 * @author Lee 
 * Time: 20180403 
 * Abstract: SharePoint API的二次封装
 */

using System;
using System.Collections.Generic;
using Microsoft.SharePoint;

namespace SharePointHelper.DLL.SSOM
{
	public class Alert
    {
        #region 枚举
        /// <summary>
        /// 枚举：预定义 SharePoint 2010 alert templates
        /// http://msdn.microsoft.com/en-us/library/bb802738%28v=office.14%29.aspx
        /// </summary>
        public enum AlertTemplate
        {
            GenericList,
            DocumentLibrary,
            WebPageLibrary,
            Survey,
            Links,
            Announcements,
            Contacts,
            Events,
            Tasks,
            DiscussionBoard,
            PictureLibrary,
            XMLForm,
            DataConnectionLibrary,
            AssignedtoNotification,
        }
        

        /// <summary>
        /// 枚举：额外的过滤器，可以改变触alert报并表达为CAML查询
        /// </summary>
        public enum ChangeType
        {
            AnythingChanges,
            SomeoneElseChangesItem,
            SomeoneElseChangesItemCreatedByMe,
            SomeoneElseChangesItemLastModifiedByMe,
        }
        #endregion

        #region 查找alert
        /// <summary>
        /// 查找与list和用户匹配的alert
		/// </summary>
		/// <param name="web">Required!</param>
		/// <param name="user">optional: filter by user</param>
		/// <param name="list">optional: filter by list</param>
		/// <returns></returns>
		public static List<SPAlert> GetAlerts(SPWeb web, bool isIncludeChildWebs, SPUser user, SPList list)
		{
			List<SPAlert> alerts = null;
			try
			{
				// 初始化
				alerts = new List<SPAlert>();
				if (web == null) { throw new Exception("SPWeb passed is null"); }


				foreach (SPAlert alert in web.Alerts)
				{
					bool isAddAlert = false;
					// 根据user和list筛选
					if (user != null && list != null)
					{
						if (user.ID == alert.UserId && list.ID == alert.ListID) { isAddAlert = true; }
					}
					// 只根据用户筛选
					else if (user != null)
					{
						if (user.ID == alert.UserId) { isAddAlert = true; }
					}
					// 只根据list筛选
					else if (list != null)
					{
						if (list.ID == alert.ListID) { isAddAlert = true; }
					}
					// 不筛选，获取所有的alert
					else
					{
						isAddAlert = true;
					}

					// 添加alert
					if (isAddAlert) { alerts.Add(alert); }
				}

				// 从子站点中获取满足条件的alert
				if (isIncludeChildWebs && web.Webs.Count > 0)
				{
					List<SPAlert> childAlerts = GetAlerts(web, isIncludeChildWebs, user, list);
					if (childAlerts != null && childAlerts.Count > 0) { alerts.AddRange(childAlerts); }
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("drytutdydrasayraseyser", ex);
				alerts = null;
			}
			return alerts;
		}

		/// <summary>
		///获取某个web所有的alert
		/// </summary>
		/// <param name="web"></param>
		/// <returns></returns>
		public static List<SPAlert> GetAlerts(SPWeb web)
		{
			return GetAlerts(web, false, null, null);
		}

		/// <summary>
		/// 获取某个list相关的alert
		/// </summary>
		/// <param name="list"></param>
		/// <returns></returns>
		public static List<SPAlert> GetAlerts(SPList list)
		{
			List<SPAlert> alerts = null;
			try
			{
				if (list == null) { throw new Exception("SPList passed is null"); }
				alerts = GetAlerts(list.ParentWeb, false, null, list);
			}
			catch (Exception ex)
			{
				Log.WriteError("dfxzggcfgxdzsdsfzdsf", ex);
				alerts = null;
			}
			return alerts;
		}

		/// <summary>
		/// 获取某个用户的所有的alert
		/// </summary>
		/// <param name="list"></param>
		/// <returns></returns>
		public static List<SPAlert> GetAlerts(SPWeb web, bool isIncludeChildWebs, SPUser user)
		{
			List<SPAlert> alerts = null;
			try
			{
				if (user == null) { throw new Exception("SPUser passed is null"); }
				alerts = GetAlerts(web, isIncludeChildWebs, user, null);
			}
			catch (Exception ex)
			{
				Log.WriteError("trsuygjhdrssgdzszddzstr", ex);
				alerts = null;
			}
			return alerts;
		}
        #endregion

        #region 创建alert
        /// <summary>
        /// 创建alert
		/// http://knrs.blogspot.com/2007/11/sharepoint-programmatically-set-alert.html
		/// http://www.sharepointology.com/development/how-to-create-alerts-programmatically/
		/// </summary>
		/// <param name="alertTitle">如果是null, 就是用list的title</param>
		/// <param name="user"></param>
		/// <param name="list"></param>
		/// <param name="eventType"></param>
		/// <param name="frequency"></param>
		/// <param name="filter"></param>
		/// <param name="isOverWriteIfAlreadyExists">如果是true并且alert已经存在, 那么将会进行覆盖.</param>
		/// <param name="isSave"></param>
		/// <returns></returns>
		public static SPAlert CreateAlert(string alertTitle, SPUser user, SPList list, SPEventType eventType,
			SPAlertFrequency frequency, DateTime? alertTime, ChangeType changeType, bool isOverWriteIfAlreadyExists, bool isSave)
		{
			SPAlert alert = null;
			string username = null;
			try
			{
				// 初始化
				if (user == null) { throw new Exception("SPUser passed is null"); }
				if (list == null) { throw new Exception("SPList passed is null"); }
				username = Security.FormatUsername(user);
				if (string.IsNullOrEmpty(alertTitle)) { alertTitle = list.Title; }
				if (frequency != SPAlertFrequency.Immediate && (alertTime == null || alertTime == DateTime.MinValue))
				{
					throw new Exception("When creating an alert that isn't immediate, you must also defined the alert time");
				}

				// 检查
				List<SPAlert> existingAlerts = GetAlerts(list.ParentWeb, false, user, list);
				if (existingAlerts != null && existingAlerts.Count > 0) { alert = existingAlerts[0]; }

				// 创建alert
				if (alert == null || isOverWriteIfAlreadyExists)
				{
					bool isNewAlert = false;
					if (alert == null) { alert = list.ParentWeb.Alerts.Add(); isNewAlert = true; }

					// 基础属性
					alert.User = user;
					if (isNewAlert)
					{
						alert.AlertType = SPAlertType.List;
						alert.List = list;
					}
					alert.AlertFrequency = frequency;
					if (alertTime != null && alertTime != DateTime.MinValue) { alert.AlertTime = (DateTime)alertTime; }
					alert.Title = alertTitle;
					alert.Status = SPAlertStatus.On;
					alert.AlwaysNotify = false;
					alert.DeliveryChannels = SPAlertDeliveryChannels.Email;

					// alert template
					alert.AlertTemplate = CreateAlertTemplate(list);

					// event 类型
					// http://kitmenke.com/blog/2009/08/18/creating-a-sharepoint-alert-with-different-eventtypes/
					alert.EventType = eventType;
					switch (eventType)
					{
						case SPEventType.All:
							alert.Properties["eventtypeindex"] = "0";
							break;
						case SPEventType.Add:
							alert.Properties["eventtypeindex"] = "1";
							break;
						case SPEventType.Modify:
							alert.Properties["eventtypeindex"] = "2";
							break;
						case SPEventType.Delete:
							alert.Properties["eventtypeindex"] = "3";
							break;
						case SPEventType.Discussion:
							alert.Properties["eventtypeindex"] = "4";
							break;
						default:
							break;
					}

					// 筛选
					alert.Filter = GetChangeTypeCamlQuery(changeType, user);

					// 保存
					if (isSave) { alert.Update(false); }
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("7iryjdfsdrgszease", ex, "user: " + username);
				alert = null;
			}
			return alert;
		}
        #endregion       

        #region 格式化alert template的name (使用预定义的 OOTB templates)
        /// <summary>
		/// 格式化alert template的name (使用预定义的 OOTB templates)
		/// </summary>
		/// <param name="template"></param>
		/// <returns></returns>
		public static string FormatAlertTemplateName(AlertTemplate template)
		{
			return "SPAlertTemplateType." + template.ToString();
		}
        #endregion

        #region 根据某个list的template来获取alert的template
        /// <summary>
        /// 根据某个list的template来获取alert的template
		/// 如果不知道 list 的基础 template, 则使用通用的alert template
		/// </summary>
		/// <param name="list"></param>
		/// <returns></returns>
		public static AlertTemplate GetAlertTemplate(SPList list)
		{
			AlertTemplate template = AlertTemplate.GenericList;
			try
			{
				// 初始化
				if (list == null) { throw new Exception("SPList passed is null"); }

				foreach (AlertTemplate _template in Enum.GetValues(typeof(AlertTemplate)))
				{
					if (_template.ToString().ToLower() == list.BaseTemplate.ToString().ToLower())
					{
						// 发现匹配, use it
						template = _template;
					}
				}
			}
			catch (Exception ex)
			{
				string listUrl = null; if (list != null) { listUrl = List.GetUrl(list); }
				Log.WriteError("zsdugyffugdxyfdxrdsr", ex, "list: " + listUrl);
			}
			return template;
		}
        #endregion

        #region 根据某个list来获取alert的template的name
        /// <summary>
        /// 根据某个list来获取alert的template的name
		/// </summary>
		/// <param name="list"></param>
		/// <returns></returns>
		public static string GetAlertTemplateName(SPList list)
		{
			// 根据list获取alert template
			AlertTemplate template = GetAlertTemplate(list);

			// 调用上面的方法
			return FormatAlertTemplateName(template);
		}
        #endregion

        #region 创建 alert template
        /// <summary>
        /// 创建 alert template
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
		public static SPAlertTemplate CreateAlertTemplate(SPList list)
		{
			// 创建新的 alert template 实例
			SPAlertTemplate alertTemplate = new SPAlertTemplate();

			// 获取 alert template name
			alertTemplate.Name = GetAlertTemplateName(list);

			return alertTemplate;
		}
        #endregion

        #region  获取 SPAlert的CAML query语句 (用于筛选)
        /// <summary>
		/// 获取 SPAlert的CAML query语句 (用于筛选)
		/// </summary>
		/// <param name="changeType"></param>
		/// <param name="username"></param>
		/// <returns></returns>
		public static string GetChangeTypeCamlQuery(ChangeType changeType, SPUser user)
		{
			string caml = null;
			try
			{
				// 初始化
				if (user == null) { throw new Exception("SPUser passed is null"); }
				
				string username = Security.FormatUsername(user);


				if (changeType == ChangeType.AnythingChanges)
				{
					caml = string.Empty;
				}
				else if (changeType == ChangeType.SomeoneElseChangesItem)
				{
					caml = "<Neq><Value type=\"string\">" + username + "</Value><FieldRef Name=\"Editor/New\"/></Neq>";
				}
				else if (changeType == ChangeType.SomeoneElseChangesItemCreatedByMe)
				{
					caml = "<And><Or><Eq><Value type=\"string\">"
						+ username + "</Value><FieldRef Name=\"Author/New\"/></Eq><Eq><Value type=\"string\">"
						+ username + "</Value><FieldRef Name=\"Author/Old\"/></Eq></Or><Neq><Value type=\"string\">"
						+ username + "</Value><FieldRef Name=\"Editor/New\"/></Neq></And>";
				}
				else if (changeType == ChangeType.SomeoneElseChangesItemLastModifiedByMe)
				{
					caml = "<And><Eq><Value type=\"string\">"
						+ username + "</Value><FieldRef Name=\"Editor/Old\"/></Eq><Neq><Value type=\"string\">"
						+ username + "</Value><FieldRef Name=\"Editor/New\"/></Neq></And>";
				}
				else
				{
					throw new Exception("Unknown Change Type: " + changeType.ToString());
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("uyi7t5et4esrdxf", ex);
				caml = null;
			}
			return caml;
        }
        #endregion



    }
}
